﻿using System;
using System.Collections.Generic;
using System.Text;
using Model = SharePointOptimizer.Model;
using System.Linq;
using System.Data.SqlClient;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using System.Data.SqlTypes;
using AG.Utilities;
using SharePointOptimizer.Model;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Management;
using System.Management.Instrumentation;
using Microsoft.SharePoint.Administration.Backup;
using System.Xml;

namespace SharePointOptimizer.SQLServer
{
    
    public class CollectSharePointFarmData
    {
        List<Exception> errors;
        SharePointOptimizerDataContext dc;

        public void ClearAll()
        {
            dc = new SharePointOptimizerDataContext(System.Configuration.ConfigurationManager.AppSettings["ConnectionStringSSHCDatabase"].ToString());
            dc.ClearAll();
        }
        public List<Exception> Collect()
        {

            try
            {
                errors = new List<Exception>();
                dc = new SharePointOptimizerDataContext(System.Configuration.ConfigurationManager.AppSettings["ConnectionStringSSHCDatabase"].ToString());

                //TODO: KK Put collection code here
               // string connstring = SPUsageApplicationProxy.Default.DatabaseConnectionString;
                FillFarm();
                //FillWebApplicationsAndApplicationPools();
                //FillSites();
                //FillLists();

            }
            catch (Exception ex1)
            {
                Logger.Error(ex1);
            }

            return errors;
        }
        public void FillFarm()
        {
            try
            {
               
                SPFarm farm = SPFarm.Local;
                SharePointOptimizer.Model.Farm newFarm = new SharePointOptimizer.Model.Farm();
                newFarm.FarmID = farm.Id;
                newFarm.Name = farm.Name;
                newFarm.NeedsUpgrade = farm.NeedsUpgrade;
                newFarm.NeedsUpgradeIncludeChildren = farm.NeedsUpgradeIncludeChildren;
                newFarm.Version = (int)farm.Version;
                dc.Farms.InsertOnSubmit(newFarm);
                dc.SubmitChanges();
               // SPBackupRestoreSettings settings = SPBackupRestoreSettings.GetBackupSettings("C:\\Backup", "Full");
                // SPBackupRestoreConsole.CreateBackupRestore(settings);
                 SPBackupRestoreHistoryList histlist = SPBackupRestoreConsole.GetHistory("C:\\Backup");
                 for (int index = 0; index < histlist.Count; index++)
                 {
                     SPBackupRestoreHistoryObject histobj = histlist[index];
                     if (histobj.IsBackup)
                     {
                         Backup newBackup = new Backup();
                         fillBackup(histobj, newBackup);
                         dc.Backups.InsertOnSubmit(newBackup);
                         dc.SubmitChanges();
                     }
                 }
               // SPBackupRestoreHistoryList history = new SPBackupRestoreHistoryList(); 
                
                foreach (SPServer server in farm.Servers)
                {
                   
                    Server newServer = new Server();
                    fillServer(server, newServer);
                    newServer.Farm = newFarm;
                    dc.Servers.InsertOnSubmit(newServer);
                    dc.SubmitChanges();
                    foreach (SPServiceInstance servInst in server.ServiceInstances)
                    {
                        ServiceInstance newServInst = new ServiceInstance();
                        fillServInst(servInst, newServInst);
                        newServInst.Server = newServer;
                        dc.ServiceInstances.InsertOnSubmit(newServInst);
                        dc.SubmitChanges();
                        if (servInst is SPDatabaseServiceInstance)
                        {
                            SPDatabaseServiceInstance dbServInst = (SPDatabaseServiceInstance)servInst;
                            foreach (SPDatabase database in dbServInst.Databases)
                            {
                                Database newDB = new Database();
                                fillDatabase(database, newDB);
                                newDB.ServiceInstance = newServInst;
                                dc.Databases.InsertOnSubmit(newDB);
                                dc.SubmitChanges();

                            }
                        }
                    }
                }
                foreach (SPService svc in farm.Services)
                {
                    Service newService = new Service();
                    newService.Farm = newFarm;
                   
                    fillService(svc, newService);
                    dc.Services.InsertOnSubmit(newService);
                    dc.SubmitChanges();
                    foreach (SPServiceApplication serviceApp in svc.Applications)
                    {
                        ServiceApplication newServApp = new ServiceApplication();
                        newServApp.Service = newService;
                        fillServApp(serviceApp, newServApp);
                        dc.ServiceApplications.InsertOnSubmit(newServApp);
                        dc.SubmitChanges();
                    }
                    foreach (SPJobDefinition jobDef in svc.JobDefinitions)
                    {
                        JobDefinition newJobDef = new JobDefinition();
                        fillJobDef(jobDef, newJobDef);
                        Service_JobDefinition servJobDef = new Service_JobDefinition();
                        servJobDef.JobDefinition = newJobDef;
                        servJobDef.Service = newService;
                        dc.Service_JobDefinitions.InsertOnSubmit(servJobDef);
                        dc.JobDefinitions.InsertOnSubmit(newJobDef);
                        dc.SubmitChanges();
                    }
                    int i = 1;
                    foreach (SPRunningJob runJob in svc.RunningJobs)
                    {
                        RunningJob newRunJob = new RunningJob();
                        newRunJob.RunningJobID = i;
                        fillRunJob(runJob, newRunJob);
                        Service_RunningJob servRunJob = new Service_RunningJob();
                        servRunJob.RunningJob = newRunJob;
                        servRunJob.Service = newService;
                        dc.Service_RunningJobs.InsertOnSubmit(servRunJob);
                        dc.RunningJobs.InsertOnSubmit(newRunJob);
                        dc.SubmitChanges();
                        i++;
                    }
                    if (svc is SPWebService )
                    {
                        SPWebService webSvc = (SPWebService)svc;
                        foreach (SPQuotaTemplate quotaTemplate in webSvc.QuotaTemplates)

                            foreach (SPWebApplication webApp in webSvc.WebApplications)
                            {
                                WebApplication newWebApp = new WebApplication();
                                newWebApp.WebApplicationID = webApp.Id;
                                newWebApp.Service = newService;
                                fillWebApp(webApp, newWebApp);
                                foreach (SPJobDefinition jobDef in webApp.JobDefinitions)
                                {
                                    JobDefinition newJobDef = new JobDefinition();
                                    fillJobDef(jobDef, newJobDef);
                                    WebApplication_JobDefinition webappjob = new WebApplication_JobDefinition();
                                    webappjob.JobDefinition = newJobDef;
                                    webappjob.WebApplication = newWebApp;
                                    dc.WebApplication_JobDefinitions.InsertOnSubmit(webappjob);
                                   dc.JobDefinitions.InsertOnSubmit(newJobDef);


                                }
                               
                                ApplicationPool newAppPool = new ApplicationPool();
                                newAppPool.ApplicationPoolID = webApp.ApplicationPool.Id;
                                fillAppPool(webApp.ApplicationPool, newAppPool);
                                newAppPool.Service = newService;
                                newWebApp.ApplicationPool = newAppPool;
                                dc.WebApplications.InsertOnSubmit(newWebApp);
                                dc.ApplicationPools.InsertOnSubmit(newAppPool);
                                dc.SubmitChanges();
                            }
                    }
                }
            }
            catch (Exception ex)
            {

                errors.Add(ex);
                Logger.Error(ex);
            }


        }

        void fillService(SPService svc, Service newService)
        {
            newService.CanUpgrade = svc.CanUpgrade;

            newService.ServiceID = svc.Id;

            newService.NeedsUpgrade = svc.NeedsUpgrade;
            newService.Required = svc.Required;
            newService.Status = svc.Status.ToString();
            newService.TypeName = svc.TypeName;
            newService.Version = (int)svc.Version;
            newService.CanUpgrade = svc.CanUpgrade;

            newService.NeedsUpgraeIncludeChildren = svc.NeedsUpgradeIncludeChildren;
        }
        void fillServApp(SPServiceApplication servApp, ServiceApplication newServApp)
        {
            newServApp.ServiceApplicationID = servApp.Id;

            newServApp.DisplayName = servApp.DisplayName;

            newServApp.Name = servApp.Name;
            newServApp.NeedsUpgrade = servApp.NeedsUpgrade;
            newServApp.NeedsUpgradeIncludeChildren = servApp.NeedsUpgradeIncludeChildren;

            newServApp.Status = servApp.Status.ToString();
            newServApp.TypeName = servApp.TypeName;

        }
        void fillJobDef(SPJobDefinition jobDef, JobDefinition newJobDef)
        {
            newJobDef.DiskSizeRequired = (int)jobDef.DiskSizeRequired;
            newJobDef.JobDefinitionID = jobDef.Id;
            newJobDef.IsDisabled = jobDef.IsDisabled;
            if(jobDef.LastRunTime.Year != 1)
            newJobDef.LastRunTime = jobDef.LastRunTime;
            newJobDef.Name = jobDef.Name;
            newJobDef.Retry = jobDef.Retry;
            newJobDef.Schedule = jobDef.Schedule.Description;
            newJobDef.Status = jobDef.Status.ToString();
            newJobDef.Version = (int)jobDef.Version;
           
        }
        void fillRunJob(SPRunningJob runJob, RunningJob newRunJob)
        {
            //newRunJob.RunningJobID = runJob.ID
            newRunJob.JobDefnitionID = runJob.JobDefinitionId;
            newRunJob.PercentageDone = runJob.PercentageDone;
            newRunJob.StartTime = runJob.StartTime;
            //newRunJob.Version = (int)runJob.Version;

        }
        void fillWebApp(SPWebApplication webApp, WebApplication newWebApp)
        {
            try
            {
                newWebApp.WebApplicationID = webApp.Id;
                ConfigSetting configSetting = new ConfigSetting();
                configSetting.WebApplication = newWebApp;
                int? port = GetPortNumber(webApp);
                string path = "C:\\inetpub\\wwwroot\\wss\\VirtualDirectories\\" + port.ToString() + "\\web.config";
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                XmlNode node = doc.SelectSingleNode("/configuration/system.web/compilation");
                if (node.Attributes.GetNamedItem("debug").Value == "true")
                {
                    configSetting.DebugEnabled = true;
                }
                else
                {
                    configSetting.DebugEnabled = false;
                }
                node = doc.SelectSingleNode("/configuration/SharePoint/BlobCache");
                if (node.Attributes.GetNamedItem("enabled").Value == "true")
                    configSetting.BlobCacheEnabled = true;
                else
                    configSetting.BlobCacheEnabled = false;

                configSetting.BlobCacheMaxSize = int.Parse(node.Attributes.GetNamedItem("maxSize").Value);
                node = doc.SelectSingleNode("configuration/SharePoint/ObjectCache");
                configSetting.ObjectCacheMaxSize = int.Parse(node.Attributes.GetNamedItem("maxSize").Value);
                newWebApp.NeedsUpgrade = webApp.NeedsUpgrade;
                newWebApp.NeedsUpgradeIncludeChildren = webApp.NeedsUpgradeIncludeChildren;

                newWebApp.DisplayName = webApp.DisplayName;
                dc.ConfigSettings.InsertOnSubmit(configSetting);
            }
            catch(Exception ex)
            {
                Logger.Error(ex);
            }
            //add needed fields for webaplications here
        }
            
        int? GetPortNumber(SPWebApplication application)
        {
            int? result = null;
            SPIisSettings setting = null;
            if (application.IisSettings.TryGetValue(SPUrlZone.Default, out setting))
            {
                if (null != setting)
                {
                    var serverBindings = setting.ServerBindings;
                    if (0 < serverBindings.Count)
                    {
                        SPServerBinding serverBinding = serverBindings[0];
                        result = serverBinding.Port;
                    }
                }
            }
            return result;
        }
        void fillAppPool(SPApplicationPool appPool, ApplicationPool newAppPool)
        {
            newAppPool.ApplicationPoolID = appPool.Id;

        }
        void fillDatabase(SPDatabase db, Database newDB)
        {

            newDB.DatabaseID = db.Id;
            newDB.DisplayName = db.DisplayName;
            newDB.DiskSizeRequired = (long)db.DiskSizeRequired;
            newDB.Password = db.Password;
            newDB.TypeName = db.TypeName;
            newDB.Name = db.Name;
            newDB.NeedsUpgrade = db.NeedsUpgrade;
            newDB.NeedsUpgradeIncludeChildren = db.NeedsUpgradeIncludeChildren;
            try { newDB.Password = db.Password.ToString(); }
            catch { }
            
            newDB.Username = db.Username;
            //newDB.SchemaVersionXml = db.SchemaVersionXml;

            if (db is SPContentDatabase)
            {
                SPContentDatabase conDB = (SPContentDatabase)db;
                fillConDB(conDB, newDB);
            }


        }
        void fillConDB(SPContentDatabase db, Database newDB)
        {
            newDB.CurrentSiteCount = db.CurrentSiteCount;
            newDB.MaximumSiteCount = db.MaximumSiteCount;
            newDB.WarningSiteCount = db.WarningSiteCount;
        }
        void fillServInst(SPServiceInstance servInst, ServiceInstance newServInst)
        {
            newServInst.ServiceInstanceID = servInst.Id;

            newServInst.ServiceID = servInst.Id;

            newServInst.NeedsUpgrade = servInst.NeedsUpgrade;
            newServInst.NeedsUpgradeIncludeChildren = servInst.NeedsUpgradeIncludeChildren;

            newServInst.Status = servInst.Status.ToString();
            newServInst.TypeName = servInst.TypeName;


        }
        void fillBackup(SPBackupRestoreHistoryObject backup, Backup newBackup)
        {
            newBackup.BackupID = backup.SelfId;
            newBackup.BackupMethod = backup.BackupMethod.ToString();
            newBackup.ConfigurationOnly = backup.ConfigurationOnly;
            newBackup.Directory = backup.Directory;
            newBackup.DirectoryName = backup.DirectoryName;
            try { newBackup.EndTime = backup.EndTime; }
            catch { }
            newBackup.ErrorCount = (int)backup.ErrorCount;
            newBackup.FailureMessage = backup.FailureMessage;
            newBackup.isFailure = backup.IsFailure;
            newBackup.Name = backup.Name;
            newBackup.ParentId = backup.ParentId;
            newBackup.RequestedBy = backup.RequestedBy;
            newBackup.StartTime = backup.StartTime;
            newBackup.TopComponent = backup.TopComponent;
            newBackup.TopComponentID = backup.TopComponentId;
            newBackup.WarningCount = (int)backup.WarningCount;

        }
        void fillServer(SPServer server, Server newServer)
        {

            newServer.ServerID = server.Id;
            newServer.Role = server.Role.ToString();

            newServer.Name = server.Name;
            newServer.NeedsUpgrade = server.NeedsUpgrade;

            newServer.Status = server.Status.ToString();
            newServer.TypeName = server.TypeName;

            getWMIStats(newServer);
            processCPU(newServer);
            //newServer.WasCreated = server.was
        }
        void getWMIStats(Server server)
        {
            long mb = 1048576;
            ConnectionOptions oConn = new ConnectionOptions();
            //oConn.Username = "username";
            //oConn.Password = "password";
            ManagementScope oMs = new ManagementScope(
               "\\\\" + server.Name + "\\root\\cimv2", oConn);


            //get Fixed disk stats
            System.Management.ObjectQuery oQuery = new System.Management.ObjectQuery("select FreeSpace,Size,Name from Win32_LogicalDisk where DriveType=3");
            ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oMs, oQuery);
            ManagementObjectCollection oReturnCollection = oSearcher.Get();
            foreach (ManagementObject oReturn in oReturnCollection)
            {

                Disk disk = new Disk();
                disk.Server = server;
                disk.Name = oReturn["Name"].ToString();
                disk.VolumeSerialNumber = GetHDDSerialNumber(disk.Name);


                //Used space in MB
                disk.Used = (int)((Convert.ToInt64(oReturn["Size"]) - Convert.ToInt64(oReturn["FreeSpace"])) / mb);

                //Total space in MB
                disk.Size = (int)(Convert.ToInt64(oReturn["Size"]) / mb);
                dc.Disks.InsertOnSubmit(disk);
                // dc.SubmitChanges();
            }
            ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_PhysicalMemory");

            ManagementObjectSearcher searcher = new ManagementObjectSearcher(oMs, query);
            long serverRAMCapacity = 0;
            foreach (ManagementObject queryObj in searcher.Get())
            {
                serverRAMCapacity += Convert.ToInt64(queryObj["Capacity"]);
                server.RAMMemoryType = queryObj["MemoryType"].ToString();
            }
            server.RAMCapacity = serverRAMCapacity / mb;
            query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
            searcher = new ManagementObjectSearcher(oMs, query);
            SharePointOptimizer.Model.OperatingSystem OS = new SharePointOptimizer.Model.OperatingSystem();
            foreach (ManagementObject queryObj in searcher.Get())
            {

                OS.Caption = queryObj["Caption"].ToString();
                OS.ServicePackMajorVersion = Convert.ToInt32(queryObj["ServicePackMajorVersion"]);
                OS.ServicePackMinorVersion = Convert.ToInt32(queryObj["ServicePackMinorVersion"]);
                OS.OSArchitecture = queryObj["OSArchitecture"].ToString();
                OS.Server = server;
                dc.OperatingSystems.InsertOnSubmit(OS);
                //dc.SubmitChanges();
            }

            //UNCOMMENT TO GET ERRORS, 
            /* query = new ObjectQuery("Select * from Win32_NTLogEvent where Logfile = 'Application' AND (type ='Error' OR type ='Critical')");
             searcher = new ManagementObjectSearcher(oMs, query);
             DateTime gowno = DateTime.Now;
             foreach (ManagementObject queryObj in searcher.Get())
             {
                 EventLog eventLog = new EventLog();
                 eventLog.Category = queryObj["Category"].ToString();
                 try { eventLog.CategoryString = queryObj["CategoryString"].ToString(); }
                 catch { }
                 eventLog.ComputerName = queryObj["ComputerName"].ToString();
                 try { eventLog.EventCode = queryObj["EventCode"].ToString(); }
                 catch { }
                 try { eventLog.EventIdentifier = queryObj["EventIdentifier"].ToString(); }
                 catch { }
                 eventLog.EventType = queryObj["EventType"].ToString();
                 eventLog.Logfile = queryObj["Logfile"].ToString();
                 try { eventLog.Message = queryObj["Message"].ToString(); }
                 catch { }
                 eventLog.RecordNumber = Convert.ToInt32(queryObj["RecordNumber"]);
                 eventLog.Server = server;
                 eventLog.SourceName = queryObj["SourceName"].ToString();
                 eventLog.TimeGenerated = queryObj["TimeGenerated"].ToString();
                 eventLog.Type = queryObj["Type"].ToString();
                 try { eventLog.User = queryObj["User"].ToString(); }
                 catch { }


                 dc.EventLogs.InsertOnSubmit(eventLog);
                 //dc.SubmitChanges();
             }*/
        }
        public string GetHDDSerialNumber(string drive)
        {
            //check to see if the user provided a drive letter
            //if not default it to "C"
            if (drive == "" || drive == null)
            {
                drive = "C";
            }
            //create our ManagementObject, passing it the drive letter to the
            //DevideID using WQL
            ManagementObject disk = new ManagementObject("Win32_LogicalDisk.DeviceID=\"" + drive + "\"");
            //bind our management object
            disk.Get();
            //return the serial number
            return disk["VolumeSerialNumber"].ToString();
        }


        /// <summary>
        /// method to retrieve the CPU's current
        /// clock speed using the WMI class
        /// </summary>
        /// <returns>Clock speed</returns>
        public void processCPU(Server server)
        {
            //int cpuClockSpeed = 0;
            //create an instance of the Managemnet class with the
            //Win32_Processor class
            ManagementClass mgmt = new ManagementClass("Win32_Processor");
            //create a ManagementObjectCollection to loop through
            ManagementObjectCollection objCol = mgmt.GetInstances();
            //start our loop for all processors found
            foreach (ManagementObject obj in objCol)
            {
                CPU cpu = new CPU();
                cpu.Server = server;
                cpu.Status = obj.Properties["Status"].Value.ToString();
                cpu.ClockSpeed = obj.Properties["CurrentClockSpeed"].Value.ToString();
                cpu.Manufacturer = obj.Properties["Manufacturer"].Value.ToString();
                cpu.CPUID = obj.Properties["ProcessorId"].Value.ToString();
                cpu.Cores = Convert.ToInt32(obj.Properties["NumberOfCores"].Value);
                //dc.SubmitChanges();

            }
            //return the status

        }
    }



}